// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Y [author] rhyme_lph
// U [email]  rhymelph@gmail.com
// W [github] https://github.com/rhymelph

import 'dart:async';

import 'package:base_plugin/base_plugin.dart';
import 'package:dio/src/response.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/entities/employee_contact_entity.dart';
import 'package:finance_app/src/http_service/http_employee_contact_service.dart';
import 'package:finance_app/src/mixin/format_group_map_mixin.dart';
import 'package:finance_app/src/mixin/refresh_mixin.dart';
import 'package:finance_app/src/mixin/search_data_list_mixin.dart';
import 'package:finance_app/src/provider/dashboard_provider.dart';
import 'package:finance_app/src/provider/hr_payroll/hr_and_payroll_provider.dart';
import 'package:finance_app/src/router_gen/override_route_providers.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/utils/permission_utils.dart';
import 'package:finance_app/src/widgets/bottom_sheet/list_select_bottom_sheet.dart';
import 'package:flutter/widgets.dart';

class EmployeeProvider extends BaseProvider<List<EmployeeContactEntity>>
    with
        SearchDataListMixin,
        RefreshMixin<List<EmployeeContactEntity>, List<EmployeeContactEntity>>,
        FormatGroupMapLocalMixin<EmployeeContactEntity> {
  String employmentStatus = 'Existing';

  List<String> menuList = [
    S.current.import,
    S.current.add,
    S.current.mark_as_resigned,
  ];

  String getStatus() {
    String status;
    if (employmentStatus == 'Existing') {
      status = 'open';
    } else if (employmentStatus == 'Left') {
      status = 'closed';
    }
    return status;
  }

  ScrollController controller = ScrollController();

  @override
  void initState() {
    super.initState();
    controller.addListener(() {
      getParentProvider<HrAndPayrollProvider>()?.handleScrollUpdate(controller);
    });
  }

  @override
  Future get dataFuture => HttpEmployeeContactService.contactList(getStatus());

  void onChangeType() {
    obtainContext?.call((context) async {
      final String result =
          await showEmploymentStatusBottomSheet(context, employmentStatus);
      if (result != null && employmentStatus != result) {
        employmentStatus = result;
        update();
        //更改父类的Provider
        final hr = getParentProvider<HrAndPayrollProvider>();
        if (employmentStatus == 'Left') {
          hr.menuList = menuList = ['Duplicate As New'];
        } else if (employmentStatus == 'Existing') {
          hr.menuList = menuList = [S.current.add, S.current.mark_as_resigned];
        } else {
          hr.menuList = menuList = [
            S.current.add,
            S.current.mark_as_resigned,
            S.current.duplicate_as_new
          ];
        }
        hr.update();
        await post(dataFuture,
            loadingTip: S.current.loading,
            autoHandler: AutoHandler.Toast, onSuccess: (result) {
          data = getEntityFromResult<List<EmployeeContactEntity>>(result);
          data = transformData(data, false);
          update();
        });
      }
    });
  }

  void contactToMap(List<EmployeeContactEntity> list) {
    sortGroupToMap(
      list,
      sort: (a, b) => sortNameFirst(a, b, (t) => t.name),
      group: (a) => groupFirstName(a, (t) => t.name),
      filter: (a) {
        if (Config.isStaff) {
          return a.userId == Config.userProfile.id;
        } else {
          bool isStatus = true;
          if (employmentStatus == 'Existing') {
            isStatus = a.resignedAt == null;
          } else if (employmentStatus == 'Left') {
            isStatus = a.resignedAt != null;
          }
          return isStatus && onFilterSearch(searchController.text, a.name);
        }
      },
      itemBefore: (map, b) => meBefore(map, b, (b) => b.userId),
    );
    if (groupMap['Me'] == null || groupMap['Me'].length == 0) {
      groupMap.remove('Me');
    }
  }

  @override
  FutureOr<List<EmployeeContactEntity>> transformData(
      List<EmployeeContactEntity> d, bool isCache) {
    groupMap.clear();
    contactToMap(d);
    return d;
  }

  void onNavDetail(EmployeeContactEntity data) async {
    unFocus();
    final result = await Routes.navigateTo(RouterGenProviders.newEmployeePage,
        params: {'data': data});
    if (result != null && result is EmployeeContactEntity) {
      data.fromJson(result.toJson());
      update();
    }
  }

  @override
  List<EmployeeContactEntity> get dataList => data;

  @override
  List<EmployeeContactEntity> getFromRequestResult(
      Response<dynamic> result, bool isRefresh) {
    List<EmployeeContactEntity> data =
        getEntityFromResult<List<EmployeeContactEntity>>(result);
    return transformData(data, false);
  }

  @override
  Future get refreshFuture => dataFuture;

  @override
  void searchRefreshData(searchData) {
    transformData(data, false);
    update();
  }

  void updateResigned(int id, String resignedDate) {
    final finder =
        data.firstWhere((element) => element.id == id, orElse: () => null);
    if (finder != null) {
      finder.resignedAt = resignedDate;
      transformData(data, false);
      update();
    }
  }

  void updateEmployee(EmployeeContactEntity entity) {
    final finder = data.firstWhere((element) => element.id == entity.id,
        orElse: () => null);
    if (finder != null) {
      finder.fromJson(entity.toJson());
    } else {
      data.add(entity);
    }
    transformData(data, false);
    update();
  }

  @override
  Future<void> onRefresh() async {
    await Providers.get<HrAndPayrollProvider>(
            RouterGenProviders.hrAndPayrollPage, null)
        ?.loadEmployeeDots();

    if (!Config.hasPermission(PermissionUtils.homeDashboard))
      Config.dashboardProvider
          ?.getChildProvider<HrAndPayrollProvider>()
          ?.loadEmployeeDots();
    return super.onRefresh();
  }
}
